﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JigLibX.Physics;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;
using JigLibX.Utils;
using Microsoft.Xna.Framework;

namespace DARE
{
    public class CVisibleRayScan : IUpdateable
    {

    #region fields

        private CRender3D m_render;
        private CRayScanner m_rayScanner;
        private bool m_orientate;
        private List<CNode> m_spheres;
        private float m_sphereScale;
        private bool m_active;

    #endregion

    #region properties

        public Vector3 Position
        {
            get { return m_rayScanner.Position; }
            set { m_rayScanner.Position = value; }
        }

        public bool Orientate
        {
            get { return m_orientate; }
            set { m_orientate = value; }
        }

        public float ScanStep
        {
            get { return m_rayScanner.ScanStep; }
            set { m_rayScanner.ScanStep = value; }
        }

        public float SphereScale
        {
            get { return m_sphereScale; }
            set { m_sphereScale = value >= 0 ? value : 0; }
        }

        public bool Active
        {
            get { return m_active; }
            set 
            {
                if (m_active != value)
                {
                    Updatable = value;
                    foreach (CNode node in m_spheres)
                        node.IsActive = value;
                    m_active = value;
                }
            }
        }

    #endregion

    #region ctor

        public CVisibleRayScan(CRender3D render)
        {
            Initialize(render, Vector3.UnitY * 20.0f, 4, 4, 0.5f);
        }

        public CVisibleRayScan(CRender3D render, Vector3 position, int scanWidth, int scanHeight, float scanStep)
        {
            Initialize(render, position, scanWidth, scanHeight, scanStep);
        }

        private void Initialize(CRender3D render, Vector3 position, int scanWidth, int scanHeight, float scanStep)
        {
            Updatable = true;
            CDare.Instance.UpdatableComponent.Add(this);
            m_render = render;
            m_rayScanner = new CRayScanner(render);
            m_rayScanner.Position = position;
            m_rayScanner.ScanWidth = scanWidth;
            m_rayScanner.ScanHeight = scanHeight;
            m_rayScanner.ScanStep = scanStep;
            m_orientate = false;
            m_spheres = new List<CNode>();
            m_sphereScale = 1;
            CNode sphere;
            for (int i = 0; i < m_rayScanner.ScanHeight * m_rayScanner.ScanWidth; ++i)
            {
                sphere = m_render.CreateNode(EType.STATIC, true);
                CBasicModel model = new CBoxModel(0.15f, 0.15f, 0.15f);
                model.Color = Color.Red;
                model.FillMode = Microsoft.Xna.Framework.Graphics.FillMode.Solid;
                model.Scale = Vector3.One * m_sphereScale;
                sphere.Entity.AttachModel(model);
                m_spheres.Add(sphere);
            }
            Active = true;
        }

        public void Destroy()
        {
            CDare.Instance.UpdatableComponent.Remove(this);
            foreach (CNode node in m_spheres)
                node.Remove();
                //node.Destroy();
        }

    #endregion

    #region methods

    #endregion

    #region implement

        public void Update(GameTime gameTime)
        {
            m_rayScanner.ProcessScan();
            CRayCast.CIntersectInfo rayInfo;
            CNode sphereNode;
            CBasicModel sphereModel;
            int sphereNum = -1;
            for (int height = 0; height < m_rayScanner.ScanHeight; ++height)
                for (int width = 0; width < m_rayScanner.ScanWidth; ++width)
                    if ((rayInfo = m_rayScanner.ScanMatrice[height, width]) != null)
                    {
                        sphereNode = m_spheres[++sphereNum];
                        if (m_orientate == true)
                            sphereNode.Orientation = CNode.NormalToNodeOrientation(rayInfo.normal);
                        sphereModel = sphereNode.Entity.Model as CBasicModel;
                        sphereModel.Color = (rayInfo.node.Entity.Physic.CollisionType != APhysicObject.ECollisionType.GROUND) ? 
                            Color.Purple : Color.Red;
                        sphereModel.Scale = Vector3.One * m_sphereScale;
                        sphereNode.SetPosition(rayInfo.pos, CNode.ESpace.WORLD);
                    }
        }

        public bool Updatable
        { get; set; }

    #endregion

    }
}
